/*
* Copyright (C) 2006, 2007 Dennis Hunziker, Ueli Kistler
* Copyright (C) 2007 Reto Schuettel, Robin Stocker
*/
package org.python.pydev.refactoring.coderefactoring.inlinelocal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Assign;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.exprType;
import org.python.pydev.parser.jython.ast.expr_contextType;
import org.python.pydev.refactoring.ast.adapters.AbstractScopeNode;
import org.python.pydev.refactoring.ast.visitors.LocalVariablesVisitor;
import org.python.pydev.refactoring.core.base.AbstractPythonRefactoring;
import org.python.pydev.refactoring.core.base.RefactoringInfo;
import org.python.pydev.refactoring.core.change.IChangeProcessor;
import org.python.pydev.refactoring.messages.Messages;
public class InlineLocalRefactoring extends AbstractPythonRefactoring {
private InlineLocalRequestProcessor requestProcessor;
private IChangeProcessor changeProcessor;
public InlineLocalRefactoring(RefactoringInfo info) {
super(info);
initWizard();
}
private void initWizard() {
this.requestProcessor = new InlineLocalRequestProcessor(info);
}
@Override
protected List<IChangeProcessor> getChangeProcessors() {
List<IChangeProcessor> processors = new ArrayList<IChangeProcessor>();
this.changeProcessor = new InlineLocalChangeProcessor(getName(), this.info, this.requestProcessor);
processors.add(changeProcessor);
return processors;
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
AbstractScopeNode<?> scope = info.getScopeAdapter();
ITextSelection selection = info.getUserSelection();
SimpleNode node = scope.getASTNode();
LocalVariablesVisitor visitor = new LocalVariablesVisitor();
try {
node.accept(visitor);
} catch (Exception e) {
throw new RuntimeException(e);
}
List<Name> variables = visitor.getVariables();
Name selectedVariable = findSelectedVariable(selection, variables);
if (selectedVariable == null) {
status.addFatalError(Messages.validationNoNameSelected);
return status;
}
List<Name> relatedVariables = findAllRelatedVariables(variables, selectedVariable);
Assign assignment = findAssignment(relatedVariables);
if (assignment == null) {
String id = selectedVariable.id;
status.addFatalError(Messages.format(Messages.inlinelocalNoAssignment, id));
return status;
}
if (!isValid(relatedVariables)) {
return status;
}
requestProcessor.setAssign(assignment);
requestProcessor.setVariables(relatedVariables);
return status;
}
private boolean isValid(List<Name> variables) {
int assignCounter = 0;
for (Name variable : variables) {
if (variable.parent instanceof Assign) {
Assign assign = (Assign) variable.parent;
/* The given name has to be one of the targets of this assignment */
for (exprType x : assign.targets) {
if (x == variable) {
assignCounter++;
break;
}
}
}
if (variable.ctx == expr_contextType.Param || variable.ctx == expr_contextType.KwOnlyParam) {
status.addFatalError(Messages.format(Messages.inlineLocalParameter, variable.getId()));
return false;
}
}
if (assignCounter > 1) {
status.addFatalError(Messages.format(Messages.inlineLocalMultipleAssignments, variables.get(0).getId()));
return false;
}
return true;
}
private Assign findAssignment(List<Name> relatedVariables) {
/* Search for the assignment */
for (Name variable : relatedVariables) {
SimpleNode parent = variable.parent;
if (parent instanceof Assign) {
Assign assign = (Assign) parent;
/* The given name has to be one of the targets of this assignment */
for (exprType x : assign.targets) {
if (x == variable) {
return assign;
}
}
}
}
return null;
}
private List<Name> findAllRelatedVariables(List<Name> variables, Name selectedVariable) {
List<Name> relatedVariables = new LinkedList<Name>();
for (Name variable : variables) {
if (variable.id.equals(selectedVariable.id)) {
relatedVariables.add(variable);
}
}
return relatedVariables;
}
private Name findSelectedVariable(ITextSelection selection, List<Name> variables) {
int selectionOffset = selection.getOffset();
for (Name variable : variables) {
int nodeLength = variable.id.length();
int nodeOffsetBegin = org.python.pydev.parser.visitors.NodeUtils.getOffset(info.getDocument(), variable);
int nodeOffsetEnd = nodeOffsetBegin + nodeLength;
if (selectionOffset >= nodeOffsetBegin && selectionOffset <= nodeOffsetEnd) {
return variable;
}
}
return null;
}
@Override
public String getName() {
return Messages.inlineLocalLabel;
}
public InlineLocalRequestProcessor getRequestProcessor() {
return requestProcessor;
}
}